"""
文件名:Base.py
    基础类:对selenium进行二次封装
    - 打开浏览器
    - 输入网址
    - 浏览器前进/后退/刷新
    - 元素定位
    - 元素操作
      - 点击
      - 输入/清空
      - 获取元素属性
      - 获取元素文本
    - 控件操作
公共方法:在项目中,一般由专人维护
"""

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.select import Select


def open_browser(browser: str = 'chrome'):
    """
    打开浏览器
    :param browser: 浏览器名称
    :return:
    """
    if browser.lower() == 'chrome':
        return webdriver.Chrome()
    elif browser.lower() == 'firefox':
        return webdriver.Firefox()
    elif browser.lower() == 'edge':
        return webdriver.Edge()
    else:
        print('请使用正确的浏览器,例如Chrome,Firefox,Edge')
        return None


class Base(object):
    def __init__(self, driver):
        self.driver = driver

    def open_url(self, url: str):
        """
        输入网址
        :param url: 项目地址
        :return:
        """
        try:
            if url.startswith('http://'):  # 判断地址是否以http://开头
                self.driver.get(url)  # 输入网址
                self.driver.maximize_window()  # 浏览器最大化
            elif url.startswith('https://'):
                self.driver.get(url)
                self.driver.maximize_window()
            else:
                new_url = 'http://' + url
                self.driver.get(new_url)
                self.driver.maximize_window()
        except:
            print('您输入的地址不规范')

    def find_element(self, locator: tuple, timeout=10):
        """
        元素定位,定位单个元素,如果元素存在,返回元素本身,反之,返回False
        :param locator: 定位器('id','kw')
        :param timeout: 超时时间
        :return: WebElement  False
        """
        try:
            return WebDriverWait(self.driver, timeout).until(EC.presence_of_element_located(locator))
        except:
            print(f'元素{locator},不存在')
            return False

    def find_elements(self, locator: tuple, timeout=10):
        """
        元素定位,定位一组元素,如果元素存在,返回元素列表,反之,返回False
        :param locator: 定位器
        :param timeout: 超时时间
        :return: list False
        """
        try:
            return WebDriverWait(self.driver, timeout).until(EC.presence_of_all_elements_located(locator))
        except:
            print(f'元素{locator},不存在')
            return False

    def send_keys(self, locator: tuple, text, timeout=10):
        """
        输入
        :param locator: 定位器
        :param text: 要输入的内容
        :param timeout: 超时时间
        :return:
        """
        element = self.find_element(locator=locator, timeout=timeout)
        if element is not False:
            element.send_keys(text)
        else:
            print(f'元素{locator},不存在,无法进行输入操作')

    def click(self, locator: tuple, timeout=10):
        """
        点击
        :param locator: 定位器
        :param timeout: 超时时间
        :return:
        """
        element = self.find_element(locator=locator, timeout=timeout)
        if element is not False:
            element.click()
        else:
            print(f"元素{locator}不存在,无法执行点击操作")

    def close_browser(self):
        """
        关闭浏览器
        :return:
        """
        self.driver.quit()

    def clear(self, locator: tuple, timeout=10):
        """
        清空
        :param locator: 定位器
        :param timeout: 超时时间
        :return:
        """
        element = self.find_element(locator=locator, timeout=timeout)
        if element is not False:
            element.clear()
        else:
            print(f"元素{locator}不存在,无法执行清空操作")

    def back_browser(self):
        """
        回退浏览器
        :return:
        """
        self.driver.back()

    def get_element_text(self, locator: tuple, timeout=10):
        """
        获取元素文本值
        :param locator:定位器
        :param timeout: 超时时间
        :return: text/False
        """
        element = self.find_element(locator=locator, timeout=timeout)
        if element is not False:
            return element.text
        else:
            return False

    def is_text_equal_in_element(self, locator: tuple, text, timeout=10):
        """
        判断已知的文本值是否和元素的文本值相同,如果相同,返回True,反之返回False
        :param locator: 定位器
        :param timeout: 超时时长
        :return: True/False
        """
        result_text = self.get_element_text(locator=locator, timeout=timeout)
        if result_text is not False:
            return result_text == text

    def drop_down_list(self, locator: tuple, text, timeout=10):
        """
        操作下拉菜单
        """
        element = self.find_element(locator=locator, timeout=timeout)
        if element is not False:
            return Select(element).select_by_visible_text(text)
        else:
            return False

    def switch_alert(self, option, input_str=None):
        '''
        对系统弹窗做出操作:
        1.只有弹窗，点击确定关闭
        2.有确认或取消两个按钮，选择按钮后关闭
        3.有输入框的弹窗，输入文字后点击确定按钮关闭
        :param option: 点击“确认”或“取消”
        :param input_str: 输入的字符
        '''
        alert = self.driver.switch_to.alert
        if option == 'accept':
            if input_str != None:
                alert.send_keys(input_str)
                alert.accept()
            else:
                alert.accept()
        else:
            alert.dismiss()

    def scroll_down(self):
        """
        滚动条向下
        :return:
        """
        js_down = "window.scrollTo(0,500)"  # 向下滚动
        self.driver.execute_script(js_down)

    def scroll_up(self):
        """
        滚动条向上
        :return:
        """
        js_up = "window.scrollTo(0,0)"  # 向上滚动,回到原点
        self.driver.execute_script(js_up)

    def gain_switch_alert(self):
        """获取弹窗文本值"""

        alert = self.driver.switch_to.alert
        return alert.text


if __name__ == '__main__':
    badiu_url = 'http://www.baidu.com/'
    base = Base(open_browser())  # 实例化
    base.open_url(badiu_url)
    locator = ('id', 'kw')
    base.find_element(locator)
    base.send_keys(locator=locator, text="web自动化")
    click_loc = ('id', 'su')
    base.click(click_loc)
    base.close_browser()
